package com.zoe.mallserver.receiver;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.rabbitmq.client.Channel;
import com.zoe.vhr.enums.MailConfigEnum;
import com.zoe.vhr.model.Employee;
import com.zoe.vhr.utils.RabbitUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.connection.PublisherCallbackChannel;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.mail.MailProperties;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
import org.springframework.stereotype.Component;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;

import javax.annotation.Resource;
import javax.mail.internet.MimeMessage;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * @Author Zoe.Zhang
 * @Date: 2021/08/14
 * @Description 消息接收
 */
@Component
public class MailReceiver {
    private static final Logger logger = LoggerFactory.getLogger(MailReceiver.class);
    @Autowired
    JavaMailSender javaMailSender;
    @Autowired
    MailProperties mailProperties;
    @Autowired
    TemplateEngine templateEngine;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private RabbitTemplate rabbitTemplate;

    @RabbitListener(queues = MailConfigEnum.MAIL_QUEUE_NAME)
    public void handler(Message<Employee> message, Channel channel) throws IOException {
        MessageHeaders headers = message.getHeaders();
        Long msgTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);

        String msgId = (String) headers.get(PublisherCallbackChannel.RETURNED_MESSAGE_CORRELATION_KEY);
        String msgId2 = (String) headers.get(MailConfigEnum.CONSUMER_MSG_ID);

        System.out.println(StrUtil.equals(msgId2, msgId));
        Employee employee = message.getPayload();
        try {
            Boolean exit = stringRedisTemplate.opsForValue().setIfAbsent("emp:" + msgId, "primary", 10L, TimeUnit.SECONDS);
            if (Boolean.FALSE.equals(exit)) {
                channel.basicAck(msgTag, false);
                logger.info("消息已经被消费过了===>{}", msgId);
                return;
            }
            // 演示异常情况下,交给死信队列处理
            // int i = 1 / 0;
            logger.info("开始发送邮件===>" + DateUtil.date());
            MimeMessage msg = javaMailSender.createMimeMessage();
            MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(msg);
            mimeMessageHelper.setFrom(mailProperties.getUsername());
            mimeMessageHelper.setTo(employee.getEmail());
            mimeMessageHelper.setSubject("入职欢迎");
            mimeMessageHelper.setSentDate(DateUtil.date());
            // 邮件模板文件名称 template目录下
            Context context = new Context();
            context.setVariable("name", employee.getName());
            context.setVariable("posName", employee.getPosition().getName());
            context.setVariable("joblevelName", employee.getjObLevel().getName());
            context.setVariable("departmentName", employee.getDepartment().getName());
            String mail = templateEngine.process("mail", context);
            mimeMessageHelper.setText(mail, true);
            javaMailSender.send(msg);

            channel.basicAck(msgTag, false);
            logger.info("邮件发送完成===>" + DateUtil.date());
        }
        catch (Exception e) {
            e.printStackTrace();
            // 重新入队 => 死信交换机不会处理
            // channel.basicNack(msgTag, false, true);

            // 不重新入队 => 交给死信会处理
            channel.basicNack(msgTag, false, false);
            // 这里不能用new CorrelationData(msgId)来发送消息id,否则消费端那边是取不到ID的

            rabbitTemplate.convertAndSend(MailConfigEnum.DELAYED_EX, MailConfigEnum.DELAYED_ROUTING_KEY, employee, RabbitUtil.customMsgId(msgId), new CorrelationData(msgId));
            logger.error("邮箱发送失败!!==>交给死信队列处理" + msgId);
        }
    }
}
